import 'dart:io';

import 'package:extended_image/extended_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:matisse_android_plugin/src/toast_utils.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';

import 'clip_image_head_border_page.dart';


///媒体类型
enum MatisseType { image, video, all }

///屏幕类型
enum ScreenOrientation {
  Horizontal, //横屏
  Vertical, //竖屏
  Sensor, //跟随传感器
}

///图片视频选择器工具类
///
/// (默认方向:强制竖屏)
/// (默认网格数：3)
class ClipImageHeadBorderUtil {
  static const MethodChannel _channel =
  MethodChannel("plugins.flutter.ztstech.com/matisse_plugin");

  //默认列数
  static const int sDeafaultColumnCount = 4;

  /// 选择全部类型文件
  ///
  ///  maxImageSize 最大图片数
  ///  maxVideoSize 最大视频数
  ///  isCanMixSelect 是否能同时选择
  ///  orientation 屏幕方向
  ///  spanCount 网格横向允许数量
  ///  videoDurationLimit 视频时长极限 (S)
  ///  videoDurationMinLimit 视频时长最短限制（S）
  ///  videoMemoryLimit 视频内存大小限制 （KB）
  ///  imageMemoryLimit 图片内存大小限制（KB）
  ///  imageRadioMaxLimit 图片宽高比例最大限制（double）
  ///  imageRadioMinLimit 图片宽度比例最小限制（double）
  ///  imageWidthMaxLimit 图片最大宽度限制（PX）
  ///  imageHeightMaxLimit 图片最大高度限制 (PX)
  ///  maxAutoFinish 最大自动退出（Android完成，IOS待开发）
  static Future<List<String>> selectAll(
      {BuildContext context,
        final int maxImageSize,
        final int maxVideoSize,
        final bool isCanMixSelect,
        final ScreenOrientation orientation,
        final int videoDurationLimit,
        final int imageMemoryLimit,
        final int videoDurationMinLimit,
        final int videoMemoryLimit,
        final double imageRadioMaxLimit,
        final double imageRadioMinLimit,
        final int imageWidthMaxLimit,
        final int imageHeightMaxLimit,
        final bool maxAutoFinish,
        final int spanCount = sDeafaultColumnCount}) async {
    if (_channel == null) {
      return null;
    }
    String permissionStr = await matissPermission();
    if (!isEmpty(permissionStr)) {
      ToastUtils.toast(msg: permissionStr, context: context);
      return null;
    }
    return await _channel.invokeListMethod<String>("selectAll", {
      "maxImageSize": maxImageSize,
      "maxVideoSize": maxVideoSize,
      "isCanMixSelect": isCanMixSelect,
      "screenOrientation": transScreenTypeToValues(orientation),
      "spanCount": spanCount,
      "videoDurationLimit": videoDurationLimit,
      "imageMemoryLimit": imageMemoryLimit,
      "videoDurationMinLimit": videoDurationMinLimit,
      "videoMemoryLimit": videoMemoryLimit,
      "imageRadioMaxLimit": imageRadioMaxLimit,
      "imageRadioMinLimit": imageRadioMinLimit,
      "imageWidthMaxLimit": imageWidthMaxLimit,
      "imageHeightMaxLimit": imageHeightMaxLimit,
      "maxAutoFinish": maxAutoFinish,
    });
  }

  /// 仅选择图片
  ///
  /// maxSize 最大图片数
  /// orientation 屏幕方向
  /// spanCount 网格横向允许数量
  /// imageMemoryLimit 图片内存大小限制（KB）
  /// imageRadioMaxLimit 图片宽高比例最大限制（double）
  /// imageRadioMinLimit 图片宽度比例最小限制（double）
  /// imageWidthMaxLimit 图片最大宽度限制（PX）
  /// imageHeightMaxLimit 图片最大高度限制 (PX)
  ///  maxAutoFinish 最大自动退出（Android完成，IOS待开发）
  static Future<List<String>> selectPhoto({
    BuildContext context,
    final int maxSize,
    final bool isCanCapture,
    final ScreenOrientation orientation,
    final int spanCount = sDeafaultColumnCount,
    final int imageMemoryLimit,
    final double imageRadioMaxLimit,
    final double imageRadioMinLimit,
    final int imageWidthMaxLimit,
    final int imageHeightMaxLimit,
    final bool maxAutoFinish,
  }) async {
    if (_channel == null) {
      return null;
    }
    String permissionStr = await matissPermission();
    if (!isEmpty(permissionStr)) {
      ToastUtils.toast(msg: permissionStr, context: context);
      return null;
    }
    return await _channel.invokeListMethod<String>("selectPhoto", {
      "maxSize": maxSize,
      "screenOrientation": transScreenTypeToValues(orientation),
      "isCanCapture": isCanCapture,
      "spanCount": spanCount,
      "imageMemoryLimit": imageMemoryLimit,
      "imageRadioMaxLimit": imageRadioMaxLimit,
      "imageRadioMinLimit": imageRadioMinLimit,
      "imageWidthMaxLimit": imageWidthMaxLimit,
      "imageHeightMaxLimit": imageHeightMaxLimit,
      "maxAutoFinish": maxAutoFinish,
    });
  }

  ///仅选择视频
  ///
  /// maxSize 最大视频数
  /// orientation 屏幕方向
  /// spanCount 网格横向允许数量
  /// videoDurationLimit 视频时长极限 (S)
  /// videoDurationMinLimit 视频时长最短限制（S）
  /// videoMemoryLimit 视频内存大小限制 （KB）
  ///  maxAutoFinish 最大自动退出（Android完成，IOS待开发）
  static Future<List<String>> selectVideo({
    BuildContext context,
    final int maxSize,
    final ScreenOrientation orientation,
    final int spanCount = sDeafaultColumnCount,
    final int videoDurationLimit,
    final int videoDurationMinLimit,
    final int videoMemoryLimit,
    final bool maxAutoFinish,
  }) async {
    if (_channel == null) {
      return null;
    }
    String permissionStr = await requestPhotoAndVideo();
    if (!isEmpty(permissionStr)) {
      ToastUtils.toast(msg: permissionStr, context: context);
      return null;
    }
    return await _channel.invokeListMethod<String>("selectVideo", {
      "maxSize": maxSize,
      "screenOrientation": transScreenTypeToValues(orientation),
      "spanCount": spanCount,
      "videoDurationLimit": videoDurationLimit,
      "videoDurationMinLimit": videoDurationMinLimit,
      "videoMemoryLimit": videoMemoryLimit,
      "maxAutoFinish": maxAutoFinish,
    });
  }

  ///裁剪头像
  /// orientation 屏幕方向
  /// spanCount 网格横向允许数量
  /// scaleX 横向比例
  /// scaleY 纵向比例
  /// backgroundColor 页面背景颜色
  /// maskColor 图片遮罩颜色
  /// editorConfig 取景器自定义参数（优先级高）
  /// lineWidth 取景线宽度
  /// lineColor 取景线颜色
  /// marginValue 边距
  /// leftCancelWidget 左取消样式
  /// rightClipWidget 右裁剪样式
  /// imageMemoryLimit 图片内存大小限制（KB）
  /// imageRadioMaxLimit 图片宽高比例最大限制（double）
  /// imageRadioMinLimit 图片宽度比例最小限制（double）
  /// imageWidthMaxLimit 图片最大宽度限制（PX）
  /// imageHeightMaxLimit 图片最大高度限制 (PX)
  ///  maxAutoFinish 最大自动退出（Android完成，IOS待开发）
  static Future<String> clipOneImage(
      BuildContext context, {
        String path,
        final bool isShowHeadBorderWidget,
        final bool isShowTextPrompt,
        final bool isCanCapture,
        final ScreenOrientation orientation,
        final int spanCount = sDeafaultColumnCount,
        final int scaleX,
        final int scaleY,
        final Widget topLeftWidget,
        final Color backgroundColor,
        final Color maskColor,
        final EditorConfig editorConfig,
        final double lineWidth,
        final Color lineColor,
        final double marginValue,
        final Widget leftCancelWidget,
        final Widget rightClipWidget,
        final int imageMemoryLimit,
        final double imageRadioMaxLimit,
        final double imageRadioMinLimit,
        final int imageWidthMaxLimit,
        final int imageHeightMaxLimit,
        final bool maxAutoFinish,
      }) async {
    if (_channel == null) {
      return null;
    }
    String permissionStr = await matissPermission();
    if (!isEmpty(permissionStr)) {
      ToastUtils.toast(msg: permissionStr, context: context);
      return null;
    }
    if (path == null || path.isEmpty) {
      List<String> list;

      list = await selectPhoto(
          context: context,
          maxSize: 1,
          isCanCapture: isCanCapture,
          orientation: orientation,
          spanCount: spanCount,
          imageMemoryLimit: imageMemoryLimit,
          maxAutoFinish: maxAutoFinish);
      if (list == null || list.isEmpty) {
        return Future.value("");
      } else {
        path = list[0];
      }
    }
    String clipPath =
    await Navigator.of(context).push<String>(MaterialPageRoute(
        builder: (context) => ClipImageHeadBorderPage(
          url: path ?? "",
          aspectRatio: scaleX == null && scaleY == null
              ? null
              : (scaleX ?? 1.0) / (scaleY ?? 1.0),
          topLeftWidget: topLeftWidget,
          backgroundColor: backgroundColor,
          maskColor: maskColor,
          editorConfig: editorConfig,
          lineWidth: lineWidth,
          lineColor: lineColor,
          marginValue: marginValue,
          leftCancelWidget: leftCancelWidget,
          rightClipWidget: rightClipWidget,
          isShowHeadBorderWidget: isShowHeadBorderWidget,
          isShowTextPrompt: isShowTextPrompt
        )));
    if (clipPath == null) {
      return Future.value("");
    } else {
      return Future.value(clipPath);
    }
  }



  ///发布页面选择图片视频封装
  ///
  /// maxImageSize 最大图片数
  /// maxVideoSize 最大视频数
  /// hasSize 已选数量
  /// chooseType 需要选类型
  /// orientation 屏幕方向
  /// hasImageSize （MatisseType.all 混选情况使用）
  /// hasVideSize （MatisseType.all 混选情况使用）
  /// spanCount 网格横向允许数量
  /// videoDurationLimit 视频时长极限 (S)
  /// videoDurationMinLimit 视频时长最短限制（S）
  /// videoMemoryLimit 视频内存大小限制 （KB）
  /// imageMemoryLimit 图片内存大小限制（KB）
  /// imageRadioMaxLimit 图片宽高比例最大限制（double）
  /// imageRadioMinLimit 图片宽度比例最小限制（double）
  /// imageWidthMaxLimit 图片最大宽度限制（PX）
  /// imageHeightMaxLimit 图片最大高度限制 (PX)）
  /// maxAutoFinish 最大自动退出（Android完成，IOS待开发）
  static Future<List<String>> selectFromReleasePage({
    BuildContext context,
    final int maxImageSize = 0,
    final int maxVideoSize = 0,
    final int hasSize = 0,
    final ScreenOrientation orientation,
    final int spanCount = sDeafaultColumnCount,
    final bool isCanMixSelect = false,
    final int hasImageSize,
    final int hasVideoSize,
    final MatisseType chooseType = MatisseType.all,
    final int videoDurationLimit,
    final int imageMemoryLimit,
    final int videoDurationMinLimit,
    final int videoMemoryLimit,
    final double imageRadioMaxLimit,
    final double imageRadioMinLimit,
    final int imageWidthMaxLimit,
    final int imageHeightMaxLimit,
    final bool maxAutoFinish,
  }) async {
    assert(isCanMixSelect ? hasVideoSize != null && hasVideoSize != null : true,
    "混选情况必传hasVideoSize和hasImageSize");
    assert(isCanMixSelect ? (maxVideoSize == maxImageSize) : true,
    "混选时，最大图片应等于最大视频（暂不支持混选限定类型数量）");
    assert(maxVideoSize != 0 || maxImageSize != 0, "最大数不能同时为0");

    if (_channel == null) {
      return null;
    }
    String permissionStr = await matissPermission();
    if (!isEmpty(await matissPermission())) {
      ToastUtils.toast(msg: permissionStr, context: context);
      return null;
    }
    switch (chooseType) {
    //图片
      case MatisseType.image:
        if (maxImageSize <= hasSize) {
          return null;
        } else {
          return await selectPhoto(
            context: context,
            maxSize: maxImageSize - hasSize,
            orientation: orientation,
            spanCount: spanCount,
            imageMemoryLimit: imageMemoryLimit,
            imageRadioMaxLimit: imageRadioMaxLimit,
            imageRadioMinLimit: imageRadioMinLimit,
            imageWidthMaxLimit: imageWidthMaxLimit,
            imageHeightMaxLimit: imageHeightMaxLimit,
            maxAutoFinish: maxAutoFinish,
          );
        }
        break;
    //视频
      case MatisseType.video:
        if (maxVideoSize <= hasSize) {
          return null;
        } else {
          return await selectVideo(
              context: context,
              maxSize: maxVideoSize - hasSize,
              orientation: orientation,
              spanCount: spanCount,
              videoDurationLimit: videoDurationLimit,
              videoDurationMinLimit: videoDurationMinLimit,
              videoMemoryLimit: videoMemoryLimit,
              maxAutoFinish: maxAutoFinish);
        }
        break;
    //所有
      case MatisseType.all:

      ///混选
        if (isCanMixSelect ?? false) {
          if (maxImageSize != maxVideoSize) {
            return null;
          } else {
            int tmpCount = maxImageSize - hasSize;
            if (tmpCount <= 0) {
              return null;
            } else {
              return await selectAll(
                  context: context,
                  maxImageSize: tmpCount,
                  maxVideoSize: tmpCount,
                  isCanMixSelect: true,
                  orientation: orientation,
                  spanCount: spanCount,
                  imageMemoryLimit: imageMemoryLimit,
                  videoDurationLimit: videoDurationLimit,
                  videoDurationMinLimit: videoDurationMinLimit,
                  videoMemoryLimit: videoMemoryLimit,
                  imageRadioMaxLimit: imageRadioMaxLimit,
                  imageRadioMinLimit: imageRadioMinLimit,
                  imageWidthMaxLimit: imageWidthMaxLimit,
                  imageHeightMaxLimit: imageHeightMaxLimit,
                  maxAutoFinish: maxAutoFinish);
            }
          }
        } else if (maxImageSize + maxVideoSize <= hasSize) {
          return null;
        }

        ///非混选
        else {
          int tmpImgSize = maxImageSize - (hasImageSize ?? 0);
          int tmpVidSize = maxVideoSize - (hasVideoSize ?? 0);

          if (tmpImgSize > 0 && tmpVidSize > 0) {
            return await selectAll(
              context: context,
              maxImageSize: tmpImgSize,
              maxVideoSize: tmpVidSize,
              isCanMixSelect: isCanMixSelect ?? false,
              orientation: orientation,
              spanCount: spanCount,
              imageMemoryLimit: imageMemoryLimit,
              videoDurationLimit: videoDurationLimit,
              videoDurationMinLimit: videoDurationMinLimit,
              videoMemoryLimit: videoMemoryLimit,
              imageRadioMaxLimit: imageRadioMaxLimit,
              imageRadioMinLimit: imageRadioMinLimit,
              imageWidthMaxLimit: imageWidthMaxLimit,
              imageHeightMaxLimit: imageHeightMaxLimit,
              maxAutoFinish: maxAutoFinish,
            );
          } else if (tmpVidSize > 0 && tmpImgSize <= 0) {
            return await selectVideo(
              context: context,
              maxSize: tmpVidSize,
              orientation: orientation,
              spanCount: spanCount,
              videoDurationLimit: videoDurationLimit,
              videoDurationMinLimit: videoDurationMinLimit,
              videoMemoryLimit: videoMemoryLimit,
              maxAutoFinish: maxAutoFinish,
            );
          } else if (tmpImgSize > 0 && tmpVidSize <= 0) {
            return await selectPhoto(
              context: context,
              maxSize: tmpImgSize,
              orientation: orientation,
              spanCount: spanCount,
              imageMemoryLimit: imageMemoryLimit,
              imageRadioMaxLimit: imageRadioMaxLimit,
              imageRadioMinLimit: imageRadioMinLimit,
              imageWidthMaxLimit: imageWidthMaxLimit,
              imageHeightMaxLimit: imageHeightMaxLimit,
              maxAutoFinish: maxAutoFinish,
            );
          }
        }
        break;

      default:
    }
    return null;
  }

  ///是否是图片类型
  static bool isImage(String path) {
    if (path == null || path.isEmpty) {
      return false;
    }
    List<String> typeList = ["jpg", "jpeg", "png", "bmp", "webp"];
    int index = path.lastIndexOf(".");
    String suffix = path.substring(index + 1);
    if (suffix == null || suffix.isEmpty) {
      return false;
    }
    return typeList.indexOf(suffix) != -1 ||
        typeList.indexOf(suffix.toLowerCase()) != -1;
  }

  ///是否是视频类型
  static bool isVideo(String path) {
    if (path == null || path.isEmpty) {
      return false;
    }
    List<String> typeList = [
      "mpeg",
      "mpg",
      "mp4",
      "mov",
      "3gp",
      "mkv",
      "webm",
      "ts",
      "avi",
      "3gpp",
      "3gpp2",
      "3g2",
      "m4u"
    ];
    int index = path.lastIndexOf(".");
    String suffix = path.substring(index + 1);
    if (suffix == null || suffix.isEmpty) {
      return false;
    }
    return typeList.indexOf(suffix) != -1 ||
        typeList.indexOf(suffix.toLowerCase()) != -1;
  }

  ///横屏
  static String SCREEN_HORIZONTAL = "landscape";

  ///竖屏
  static String SCREEN_VERTICAL = "portrait";

  ///跟随传感器
  static String SCREEN_SENSOR = "sensor";

  ///根据屏幕类型转化成参数对应值(默认为竖屏)
  static String transScreenTypeToValues(ScreenOrientation screenOrientation) {
    if (screenOrientation == null) {
      return SCREEN_VERTICAL;
    }
    if (screenOrientation == ScreenOrientation.Horizontal) {
      return SCREEN_HORIZONTAL;
    }
    if (screenOrientation == ScreenOrientation.Vertical) {
      return SCREEN_VERTICAL;
    }
    if (screenOrientation == ScreenOrientation.Sensor) {
      return SCREEN_SENSOR;
    }
    return SCREEN_VERTICAL;
  }

  ///配置选择器的外观
  static void setImagePickerAppearance(final Map<String, String> config) {
    if (Platform.isIOS) {
      _setIosPickerAppearance(config: config);
    }
  }

  ///IOS设置图片选择器外观
  ///
  /// 插件请求方法：
  ///     setIosPickerAppearance
  ///
  /// 插件请求参数：
  ///    oKButtonTitleColorNormal
  ///    oKButtonTitleColorDisabled
  ///    naviBgColor
  ///    naviTitleColor
  ///    naviTitleFont
  ///    barItemTextColor
  ///    barItemTextFont
  static void _setIosPickerAppearance({
    final Map<String, String> config,
  }) async {
    return await _channel.invokeMethod("selectAppearance", config);
  }

  ///删除临时文件夹文件
  static void safeDeleteTemporaryFiles() async {
    Directory directory = await getTemporaryDirectory();

    Directory tmpImageDirectory = new Directory(directory.path + "/imageTemp");

    if (tmpImageDirectory.existsSync()) {
      List<FileSystemEntity> files = tmpImageDirectory.listSync();
      if (files != null && files.length > 0) {
        files.forEach((file) {
          file.delete();
        });
      }
      print("临时文件夹清空完成");
    }
  }

  ///图片选择器必须的权限 写入/读取，照片，照相机
  static Future<String> matissPermission() async {
    PermissionStatus saveAndWritePermission = await PermissionHandler()
        .checkPermissionStatus(PermissionGroup.storage);
    PermissionStatus photoPermission =
    await PermissionHandler().checkPermissionStatus(PermissionGroup.photos);
    PermissionStatus cameraPermission =
    await PermissionHandler().checkPermissionStatus(PermissionGroup.camera);

    if (Platform.isAndroid || Platform.isIOS) {
      if (saveAndWritePermission != PermissionStatus.granted ||
          photoPermission != PermissionStatus.granted ||
          cameraPermission != PermissionStatus.granted) {
        Map<PermissionGroup, PermissionStatus> permissions =
        await PermissionHandler().requestPermissions([
          PermissionGroup.storage,
          PermissionGroup.photos,
          PermissionGroup.camera
        ]);
        bool saveGive =
            permissions[PermissionGroup.storage] == PermissionStatus.granted;
        bool photoGive =
            permissions[PermissionGroup.photos] == PermissionStatus.granted;
        bool cameraGive =
            permissions[PermissionGroup.camera] == PermissionStatus.granted;
        String androidPermissionStr = "请在设置界面给予app${!saveGive ? "读写" : ""}"
            "${!cameraGive ? "${saveGive ? "" : "、"}相机" : ""}权限";
//        String iosPermissionStr =
//            "请在设置界面给予app${(!saveGive || !photoGive) ? "照片的读写" : ""}"
//            "${!cameraGive ? "${photoGive && saveGive ? "" : "、"}相机" : ""}权限";
//
        String iosPermissionStr = "请在手机设置中打开相机相册相关权限";
        if (Platform.isAndroid) {
          if (saveGive && cameraGive) {
            return "";
          } else {
            return androidPermissionStr;
          }
        } else {
          if (saveGive && photoGive && cameraGive) {
            return "";
          } else {
            return iosPermissionStr;
          }
        }
      } else {
        ///三种权限都有
        return "";
      }
    }
    return "请在设置界面给予app读写,相册,相机权限";
  }

  ///图片选择器必须的权限 写入/读取，照片，照相机
  static Future<String> requestPhotoAndVideo() async {
    PermissionStatus saveAndWritePermission = await PermissionHandler()
        .checkPermissionStatus(PermissionGroup.storage);
    PermissionStatus photoPermission =
    await PermissionHandler().checkPermissionStatus(PermissionGroup.photos);
    if (Platform.isAndroid || Platform.isIOS) {
      if (saveAndWritePermission != PermissionStatus.granted ||
          photoPermission != PermissionStatus.granted) {
        Map<PermissionGroup, PermissionStatus> permissions =
        await PermissionHandler().requestPermissions([
          PermissionGroup.storage,
          PermissionGroup.photos,
        ]);
        bool saveGive =
            permissions[PermissionGroup.storage] == PermissionStatus.granted;
        bool photoGive =
            permissions[PermissionGroup.photos] == PermissionStatus.granted;
        String androidPermissionStr = "请在设置界面给予app${!saveGive ? "读写" : ""}"
            "${"${photoGive ? "" : "、"}相册"}权限";
//        String iosPermissionStr =
//            "请在设置界面给予app${(!saveGive || !photoGive) ? "照片的读写" : ""}"
//            "${!cameraGive ? "${photoGive && saveGive ? "" : "、"}相机" : ""}权限";
//
        String iosPermissionStr = "请在手机设置中打开相册相关权限";
        if (Platform.isAndroid) {
          if (saveGive) {
            return "";
          } else {
            return androidPermissionStr;
          }
        } else {
          if (saveGive && photoGive) {
            return "";
          } else {
            return iosPermissionStr;
          }
        }
      } else {
        ///三种权限都有
        return "";
      }
    }
    return "请在设置界面给予App读写,相册,相机权限";
  }

  /// isEmpty
  static bool isEmpty(String text) {
    return text == null || text.isEmpty;
  }
}
